home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dirut / dosdir21.zip / FNSPLIT.C < prev    next >
C/C++ Source or Header  |  1994-06-22  |  7KB  |  305 lines

  1. /*
  2.  *      C/C++ Run Time Library - Version 5.0
  3.  *
  4.  *      Copyright (c) 1987, 1992 by Borland International
  5.  *      All Rights Reserved.
  6.  *
  7.  * Modification History:
  8.  *  10-Jun-92  Borland    Original version.
  9.  *  17-May-94  J Mathews  Modified for Unix.
  10.  *   8-Jun-94  J Mathews  Added VMS handling,
  11.  *                        Added path expansion for ~ symbol on UNIX.
  12.  */
  13.  
  14. #include <string.h>
  15. #include "dosdir.h"
  16.  
  17. #ifdef UNIX
  18. #  include <pwd.h>
  19. #  define DD_MAXUSERNAME 100
  20. #endif
  21.  
  22. static void CopyIt   OF((char *dst, const char *src, unsigned maxlen));
  23.  
  24. /*---------------------------------------------------------------------*
  25.  
  26. Name            CopyIt - copies a string to another
  27.  
  28. Prototype in    local to this module
  29.  
  30. *---------------------------------------------------------------------*/
  31. static void CopyIt(dst, src, maxlen)
  32.      char *dst;
  33.      const char *src;
  34.      unsigned maxlen;
  35. {
  36.     if (dst) {
  37.         if (strlen(src) >= maxlen)
  38.         {
  39.             strncpy(dst, src, maxlen);
  40.             dst[maxlen] = 0;
  41.         }
  42.         else
  43.             strcpy(dst, src);
  44.     }
  45. }
  46.  
  47. #ifndef VMS
  48. static int  DotFound OF((char *pB));
  49.  
  50. /*---------------------------------------------------------------------*
  51.  
  52. Name            DotFound - checks for special directory names
  53.  
  54. Prototype in    local to this module
  55.  
  56. *---------------------------------------------------------------------*/
  57. static  int DotFound(pB)
  58.      char *pB;
  59. {
  60.     if (*(pB-1) == '.') pB--;
  61.     switch (*--pB) {
  62. #ifdef MSDOS
  63.     case ':'  :
  64.       if (*(pB-2) != '\0')
  65.         break;
  66.     case '\\' :
  67. #endif
  68.     case '/'  :
  69.     case '\0' :
  70.       return 1;
  71.     }
  72.     return 0;
  73. }
  74. #endif /* ?!VMS */
  75.  
  76. /*---------------------------------------------------------------------*
  77.  
  78. Name            dd_fnsplit - splits a full path name into its components
  79.  
  80. Usage           #include <dosdir.h>
  81.         int dd_fnsplit(const char *path, char * drive, char * dir,
  82.                  char * name, char * ext);
  83.  
  84. Prototype in    dosdir.h
  85.  
  86. Description     dd_fnsplit takes a file's full path name (path) as a string
  87.         in the form
  88.  
  89.         /DIR/SUBDIR/FILENAME            (UNIX)
  90.         X:\DIR\SUBDIR\NAME.EXT            (MS-DOS)
  91.         NODE::DEVICE:[PATH]NAME.EXT;VERSION    (VMS)
  92.  
  93.         and splits path into its four components. It then stores
  94.         those components in the strings pointed to by dir and
  95.         ext.  (Each component is required but can be a NULL,
  96.         which means the corresponding component will be parsed
  97.         but not stored.)
  98.  
  99.         The maximum sizes for these strings are given by the
  100.         constants MAXDRIVE, MAXDIR, MAXPATH, MAXNAME and MAXEXT,
  101.         (defined in dosdir.h) and each size includes space for
  102.         the null-terminator.
  103.  
  104.         Constant        String
  105.  
  106.         DD_MAXPATH         path
  107.         DD_MAXDRIVE        drive; includes colon; not used by UNIX
  108.         DD_MAXDIR          dir; includes leading and trailing
  109.                     backslashes for DOS or slashes for UNIX
  110.         DD_MAXFILE         filename
  111.         DD_MAXEXT          ext; includes leading dot (.)
  112.                    (not used by UNIX)
  113.  
  114.         dd_fnsplit assumes that there is enough space to store each
  115.         non-NULL component. fnmerge assumes that there is enough
  116.         space for the constructed path name. The maximum constructed
  117.         length is DD_MAXPATH.
  118.  
  119.         When dd_fnsplit splits path, it treats the punctuation as
  120.         follows:
  121.  
  122.         * drive keeps the colon attached (C:, A:, etc.).
  123.           It is not applicable to unix file system.
  124.  
  125.         * dir keeps the leading and trailing slashes
  126.           (/usr/local/bin/, /src/, etc.)
  127.  
  128.         * ext keeps the dot preceding the extension (.c, .doc, etc.)
  129.           It is not applicable to unix file system.
  130.  
  131. Return value    dd_fnsplit returns an integer (composed of five flags,
  132.         defined in dosdir.h) indicating which of the full path name
  133.         components were present in path; these flags and the components
  134.         they represent are:
  135.  
  136.             EXTENSION       an extension
  137.             FILENAME        a filename
  138.             DIRECTORY       a directory (and possibly
  139.                     sub-directories)
  140.             DRIVE           a drive specification (see dir.h)
  141.             WILDCARDS       wildcards (* or ? cards)
  142.  
  143. *---------------------------------------------------------------------*/
  144. int dd_fnsplit(pathP, driveP, dirP, nameP, extP)
  145.      const char *pathP;
  146.      char *driveP, *dirP, *nameP, *extP;
  147. {
  148.     register char   *pB;
  149.     register int    Wrk;
  150.     int     Ret;
  151.     char buf[ DD_MAXPATH+2 ];
  152.  
  153.     /*
  154.      * Set all string to default value zero
  155.      */
  156.     Ret = 0;
  157.     if (driveP) *driveP = 0;
  158.     if (dirP) *dirP = 0;
  159.     if (nameP) *nameP = 0;
  160.     if (extP) *extP = 0;
  161.  
  162.     /*
  163.      * Copy filename into template up to DD_MAXPATH characters
  164.      */
  165.     pB = buf;
  166.     while (*pathP == ' ') pathP++;
  167.     if ((Wrk = strlen(pathP)) > DD_MAXPATH)
  168.         Wrk = DD_MAXPATH;
  169.     *pB++ = 0;
  170.     strncpy(pB, pathP, Wrk);
  171.     *(pB += Wrk) = 0;
  172.  
  173.     /*
  174.      * Split the filename and fill corresponding nonzero pointers
  175.      */
  176.     Wrk = 0;
  177.     for (; ; ) {
  178.         switch (*--pB) {
  179.         case '.':
  180. #ifndef VMS
  181.           if (!Wrk && (*(pB+1) == '\0')) Wrk = DotFound(pB);
  182. #endif
  183. #if (defined(MSDOS) || defined(VMS))
  184.           if ((!Wrk) && ((Ret & EXTENSION) == 0)) {
  185.             Ret |= EXTENSION;
  186.             CopyIt(extP, pB, DD_MAXEXT - 1);
  187.             *pB = 0;
  188.           }
  189. #endif
  190.           continue;
  191. #if defined(MSDOS)
  192.         case ':'  :
  193.           if (pB != &buf[2])
  194.             continue;
  195. #elif defined(UNIX)
  196.         case '~' :
  197.           if (pB != &buf[1])
  198.             continue;
  199.           else {
  200.             /* expand path as appropriate */
  201.             struct passwd *pw = NULL;
  202.             char* tail = strchr (pB, '/');
  203.             int len;
  204.             if (tail != NULL) {
  205.               len = tail - (pB+1);
  206.               if (len > 0) {
  207.             char username[DD_MAXUSERNAME];
  208.             if (len <= DD_MAXUSERNAME)
  209.               {
  210.                 strncpy(username, pB+1, len);
  211.                 username[len] = 0;
  212.                 pw = getpwnam(username);
  213.               }
  214.               }
  215.               else
  216.             pw = getpwuid (getuid());
  217.  
  218.               if (pw != NULL && (len=strlen(pw->pw_dir)) < DD_MAXDIR)
  219.             {
  220.               strcpy(dirP, pw->pw_dir);
  221.               dirP += len;
  222.             }
  223.               else
  224.             strcpy (dirP++, "?");
  225.               CopyIt(dirP, tail, DD_MAXDIR - len - 1);
  226.               dirP += strlen(dirP);
  227.             }
  228.             else {
  229.               Wrk = 1;
  230.               if (pB[1] != 0)
  231.             pw = getpwnam (pB + 1);
  232.               else
  233.             pw = getpwuid (getuid());
  234.  
  235.               if (pw != NULL && (len=strlen(pw->pw_dir)) < DD_MAXDIR)
  236.             {
  237.               strcpy(dirP, pw->pw_dir);
  238.               dirP += len;
  239.             }
  240.               else
  241.             strcpy (dirP++, "?");
  242.             }
  243.             *pB-- = 0;
  244.             Ret |= DIRECTORY;
  245.           }
  246. #endif /* ?MSDOS */
  247.         case '\0' :
  248.           if (Wrk) {
  249.             if (*++pB)
  250.               Ret |= DIRECTORY;
  251.             CopyIt(dirP, pB, DD_MAXDIR - 1);
  252. #ifdef MSDOS
  253.             *pB-- = 0;
  254. #endif
  255.             break;
  256.           }
  257. #ifdef MSDOS
  258.         case '\\' :
  259. #endif
  260. #if (defined(MSDOS) || defined(UNIX))
  261.         case '/':
  262. #endif
  263. #ifdef VMS
  264.         case ']' :
  265.         case ':' :
  266. #endif
  267.           if (!Wrk) {
  268.             Wrk++;
  269.             if (*++pB) Ret |= FILENAME;
  270.             CopyIt(nameP, pB, DD_MAXFILE - 1);
  271.             *pB-- = 0;
  272. #ifdef MSDOS
  273.             if (*pB == 0 || (*pB == ':' && pB == &buf[2]))
  274. #else
  275.             if (*pB == 0)
  276. #endif
  277.             break;
  278.           }
  279.           continue;
  280. #ifndef VMS
  281.         case '[' :
  282. #endif
  283.         case '*' :
  284. #ifdef VMS
  285.         case '%' :
  286. #else
  287.         case '?' :
  288. #endif
  289.           if (!Wrk) Ret |= WILDCARDS;
  290.           default :
  291.             continue;
  292.         }
  293.         break;
  294.           }
  295.  
  296. #ifdef MSDOS
  297.     if (*pB == ':') {
  298.       if (buf[1]) Ret |= DRIVE;
  299.       CopyIt(driveP, &buf[1], DD_MAXDRIVE - 1);
  300.     }
  301. #endif
  302.  
  303.     return (Ret);
  304. }
  305.